package main

import (
	"fmt"
	"time"
)

// select 语句类似于 switch 语句，但是select会随机执行一个可运行的case。如果没有case可运行，它将阻塞，直到有case可运行。
// select 是Go中的一个控制结构，类似于用于通信的switch语句。每个case必须是一个通信操作，要么是发送要么是接收。
// select 随机执行一个可运行的case。如果没有case可运行，它将阻塞，直到有case可运行。一个默认的子句应该总是可运行的。

/*
   每个case都必须是一个通信
   所有channel表达式都会被求值
   所有被发送的表达式都会被求值
   如果任意某个通信可以进行，它就执行；其他被忽略。
   如果有多个case都可以运行，Select会随机公平地选出一个执行。其他不会执行。
   否则：
    如果有default子句，则执行该语句。
    如果没有default字句，select将阻塞，直到某个通信可以运行；Go不会重新对channel或值进行求值。
*/

// 示例
func example() {
	var c1, c2, c3 chan int
	var i1, i2 int
	// select是Go中的一个控制结构，类似于switch语句，用于处理异步IO操作。
	// select中的case语句必须是一个channel操作
	select {
	case i1 = <-c1:
		fmt.Printf("received ", i1, " from c1\n")
	case c2 <- i2:
		fmt.Printf("sent ", i2, " to c2\n")
	case i3, ok := (<-c3): // same as: i3, ok := <-c3
		if ok {
			fmt.Printf("received ", i3, " from c3\n")
		} else {
			fmt.Printf("c3 is closed\n")
		}
	default:
		fmt.Printf("no communication\n")
	}
}

// 1.超时判断
func timeoutJudgment() {
	// 比如在下面的场景中，使用全局resChan来接受response，
	// 如果时间超过3S,resChan中还没有数据返回，则第二条case将执行
	resChan := make(chan int)
	select {
	case data := <-resChan:
		doData(data)
	case <-time.After(time.Second * 3):
		fmt.Println("request time out")
	}
}

// 判断channel是否阻塞
func isChannelClog() {
	//在某些情况下是存在不希望channel缓存满了的需求的，可以用如下方法判断
	ch := make(chan int, 5)
	data := 0
	select {
	// 缓存满了走default
	case ch <- data:
	default:

	}
}

func doData(data int) {

}

func main() {
	example()
	timeoutJudgment()
	isChannelClog()
}
